#ifndef __INTERRUPTR_H__
#define __INTERRUPTR_H__

#include "libs/types.h"


#define SOFTIRQ_TIME 0

#define SOFTIRQ_TIME_FLAG (1 << SOFTIRQ_TIME)

struct SegmentDescriptor{
    uint16_t limitLow;
    uint32_t adddressLow : 24;
    uint8_t attr;
    uint8_t limitHigh : 4;
    uint8_t attr2 : 4;
    uint8_t addressMid;
}__attribute__((packed));

struct TSS
{
    uint32_t reserved1;
    uint64_t rsp0;
    uint64_t rsp1;
    uint64_t rsp2;
    uint64_t reserved2;
    uint64_t IST1;
    uint64_t IST2;
    uint64_t IST3;
    uint64_t IST4;
    uint64_t IST5;
    uint64_t IST6;
    uint64_t IST7;
    uint64_t reserved3;
    uint16_t reserved4;
    uint16_t ioMapBaseAddress; 
}__attribute__((packed));


struct IdtGate
{
   uint16_t addressLow;
   uint16_t seclector;
   uint8_t ist : 3;
   uint8_t reversed : 5;
   uint8_t attr;
   uint16_t addressMid; 
   uint64_t addressHigh;
}__attribute__((packed));



struct StackFrame
{
    uint64_t R15;
    uint64_t R14;
    uint64_t R13;
    uint64_t R12;
    uint64_t R11;
    uint64_t R10;
    uint64_t R9;
    uint64_t R8;
    uint64_t RBX;
    uint64_t RCX;
    uint64_t RDX;
    uint64_t RSI;
    uint64_t RDI;
    uint64_t RBP;
    uint64_t DS;
    uint64_t ES;
    uint64_t RAX;
    uint64_t FUNC;
    uint64_t ERRCODE;
    uint64_t RIP;
    uint64_t CS;
    uint64_t RFLAGS;
    uint64_t OLDRSP;
    uint64_t OLDSS;
}__attribute__((packed));



extern struct IdtGate IDT_Table[];



extern struct SegmentDescriptor GDT_Table[];

class interruptmanager;




#define MAX_SOFTINTERRUPT 64

class SoftInterruptHandler
{
private:
	/* data */
public:
    uint64_t softIrqNumber;
    
	SoftInterruptHandler(uint64_t/* args */);
	~SoftInterruptHandler();
	virtual void handleSoftInterrupt();
};



class SoftInterruptManager
{
private:
	/* data */
public:
    uint64_t softIrqStatus;
    uint64_t softIrqCounter;
	static SoftInterruptManager* SoftInterruptM;
	SoftInterruptHandler* softhandlers[MAX_SOFTINTERRUPT];
	SoftInterruptManager(/* args */);
	~SoftInterruptManager();
    void setSoftIrqStatus(uint64_t value);
    uint64_t getSoftIrqStatus();
    void registerHandler(uint64_t number,SoftInterruptHandler*);
    void unregisterHandler(uint64_t number);


};






class interrupthandler
{
private:
    /* data */
    
public:
    uint8_t interruptNum;
    char* irqName;
    uint64_t flags;
    interrupthandler(uint8_t num,interruptmanager* interrupts);
    interrupthandler(uint8_t num);
    ~interrupthandler();
    virtual StackFrame* handleInterrupt(StackFrame* fs);
    virtual void ackInterrupt();

    virtual void install(void*);
    virtual void enable();
    virtual void uninstall();
    virtual void disable();

};






class interruptmanager
{
private:
    /* data */
    
    void InitSystemIdtGate();
    void InitInterrupt();
    void SetGate(uint16_t gateSelector,uint8_t attr,uint8_t ist, uint64_t* address);
    void SetSystemTrapIdtGate(uint16_t gateSelector,uint8_t ist, uint64_t* address);
    void SetSystemIntrIdtGate(uint16_t gateSelector,uint8_t ist, uint64_t* address);
    void SetTrapIdeGate(uint16_t gateSelector,uint8_t ist, uint64_t* address);
    void SetIntrIdtGate(uint16_t gateSelector,uint8_t ist, uint64_t* address);
    static interrupthandler* handler[256];
    static void do_divide_error(uint64_t rsp,uint64_t error_code);
    SoftInterruptManager* softInterruptM;
    
public:
    int numOfTss;
    static interruptmanager* interrupm;
    static int taskManagerHaveFinish;
    interruptmanager(/* args */);
    ~interruptmanager();
    void InitTSS(uint64_t tssIndex,uint64_t* tssAddress,uint64_t stackAddress,uint64_t istAddress);
    void addHandler(interrupthandler* handler);
    void delHandler(interrupthandler* handler);
    static StackFrame* DoInterruptHandle(uint64_t num, StackFrame* fs);
    static void DoSoftInterruptHandler();
    static void HandleInterruptRequest0x20();
    static void HandleInterruptRequest0x21();
    static void HandleInterruptRequest0x22();
    static void HandleInterruptRequest0x23();
    static void HandleInterruptRequest0x24();
    static void HandleInterruptRequest0x25();
    static void HandleInterruptRequest0x26();
    static void HandleInterruptRequest0x27();
    static void HandleInterruptRequest0x28();
    static void HandleInterruptRequest0x29();
    static void HandleInterruptRequest0x2A();
    static void HandleInterruptRequest0x2B();
    static void HandleInterruptRequest0x2C();
    static void HandleInterruptRequest0x2D();
    static void HandleInterruptRequest0x2E();
    static void HandleInterruptRequest0x2F();
    static void HandleInterruptRequest0x30();
    static void HandleInterruptRequest0x31();



    static void HandleInterruptRequest0xC8();
    static void HandleInterruptRequest0xC9();
    static void HandleInterruptRequest0xCA();
    static void HandleInterruptRequest0xCB();
    static void HandleInterruptRequest0xCC();
    static void HandleInterruptRequest0xCD();
    static void HandleInterruptRequest0xCE();
    static void HandleInterruptRequest0xCF();
    static void HandleInterruptRequest0xD0();
    static void HandleInterruptRequest0xD1();

    void test();

};

#define INTERRUPTMANAGER \
interruptmanager::interrupm

#define SOFTINTERRUPTMANAGER \
SoftInterruptManager::SoftInterruptM

#endif